package com.carbon.assets.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import com.carbon.assets.common.enums.AssetsStatus;
import com.carbon.assets.common.enums.AssetsTradeStatus;
import com.carbon.assets.entity.CarbonCreditAssets;
import com.carbon.assets.entity.CarbonMetaregistry;
import com.carbon.assets.entity.CarbonMetaregistryProject;
import com.carbon.assets.mapper.CarbonCreditAssetsMapper;
import com.carbon.assets.mapper.CarbonMetaregistryMapper;
import com.carbon.assets.mapper.CarbonMetaregistryProjectMapper;
import com.carbon.assets.param.CarbonCreditAssetsAddParam;
import com.carbon.assets.param.CarbonCreditAssetsQueryParam;
import com.carbon.assets.service.CarbonCreditAssetsService;
import com.carbon.assets.vo.CarbonAssetsTotalVo;
import com.carbon.assets.vo.CarbonCreditAssetsQueryVo;
import com.carbon.assets.vo.CarbonMetaregistryQueryVo;
import com.carbon.common.api.Paging;
import com.carbon.common.service.BaseServiceImpl;
import com.carbon.domain.auth.vo.SecurityData;
import com.carbon.domain.chainmaker.api.ChainMakerServiceApi;
import com.carbon.domain.chainmaker.param.CarbonCreditAssetsParam;
import com.carbon.domain.common.constant.RocketDelayLevelConstant;
import com.carbon.domain.common.constant.RocketMqName;
import com.carbon.domain.mq.entity.AssetUploadApproval;
import com.carbon.domain.system.api.SystemServiceApi;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;


/**
 * <p>
 * 碳信用资产 服务实现类
 * </p>
 *
 */
@Slf4j
@Service
@Transactional(rollbackFor = Exception.class)
public class CarbonCreditAssetsServiceImpl extends BaseServiceImpl<CarbonCreditAssetsMapper, CarbonCreditAssets> implements CarbonCreditAssetsService {

    @Resource
    private CarbonCreditAssetsMapper carbonCreditAssetsMapper;
    @Resource
    private CarbonMetaregistryProjectMapper carbonMetaregistryProjectMapper;
    @Resource
    private CarbonMetaregistryMapper carbonMetaregistryMapper;

    @Resource
    private RocketMQTemplate mqTemplate;

    @Autowired
    private SystemServiceApi systemServiceApi;

    @Autowired
    private ChainMakerServiceApi chainMakerServiceApi;


    /**
     * 根据ID获取碳信用资产信息
     * 该方法通过调用碳信用资产Mapper获取特定ID的资产信息，并通过关联的碳元注册信息补充详细信息
     *
     * @param id 碳信用资产的唯一标识
     * @return 包含详细信息的碳信用资产查询视图对象
     */
    @Override
    public CarbonCreditAssetsQueryVo getCarbonCreditAssetsById(Serializable id) {
        // 通过ID获取碳信用资产基本信息
        CarbonCreditAssetsQueryVo vo = carbonCreditAssetsMapper.getCarbonCreditAssetsById(id);
        // 根据资产信息中的项目ID获取碳元注册信息
        CarbonMetaregistry carbonMetaregistry = carbonMetaregistryMapper.selectById(vo.getCarbonProjectId());
        //        System.out.println(carbonMetaregistry.getCertifiedStandard()
//                +" 1 "+carbonMetaregistry.getMethodologyCode()
//                +" 2 "+carbonMetaregistry.getProjectScopeTypeCode()
//                +" 3 "+carbonMetaregistry.getProjectVerifier()
//                +" 4 "+carbonMetaregistry.getIssuingDate()
//                +" 5 "+carbonMetaregistry.getProjectOwner()
//        );
        // 检查碳元注册信息是否为空
        if(carbonMetaregistry!=null) {
            // 获取认证标准信息
            String certifiedStandard=carbonMetaregistry.getCertifiedStandard();
            // 仅当认证标准不为空时，设置认证标准和发证机构
            if(certifiedStandard!=null&&certifiedStandard!="") {
                vo.setCertificationCriteria(certifiedStandard);
                // 根据不同的认证标准设置发证机构
                if(certifiedStandard.equals("CCER")) {
                    vo.setIssuingAgency("生态环境部");
                } else if(certifiedStandard.equals("VCS")) {
                    vo.setIssuingAgency("verra");
                } else if(certifiedStandard.equals("goldstandard")) {
                    vo.setIssuingAgency(certifiedStandard);
                }
            }

            // 设置碳方法学名称、项目范围类型代码、认证机构、发证日期和租户名称
            vo.setCarbonMethodologyName(carbonMetaregistry.getMethodologyCode());
            vo.setProjectScopeTypeCode(carbonMetaregistry.getProjectScopeTypeCode());
            vo.setCertifiedAgency(carbonMetaregistry.getProjectVerifier());
            vo.setIssuingDate(carbonMetaregistry.getIssuingDate());
            vo.setTenantName(carbonMetaregistry.getProjectOwner());
        }
        // 返回包含详细信息的碳信用资产查询视图对象
        return vo;
    }


    @Override
    public Paging<CarbonCreditAssetsQueryVo> getCarbonCreditAssetsPageList(CarbonCreditAssetsQueryParam param) {
        Page<?> page = getPage(param);
        page.addOrder(OrderItem.desc("cca.updated_time"));
        IPage<CarbonCreditAssetsQueryVo> iPage = carbonCreditAssetsMapper.getCarbonCreditAssetsPageList(page,param);
        List<CarbonCreditAssetsQueryVo> records = iPage.getRecords();
        ArrayList<CarbonCreditAssetsQueryVo> creditAssetsQueryVos = new ArrayList<>();
        return new Paging<>(iPage);
    }

    /**
     * 添加碳信用资产
     *
     * @param param 碳信用资产添加参数
     */
    @Override
    public void addCarbonCreditAssets(CarbonCreditAssetsAddParam param) {

        // 新建碳信用资产实体
        CarbonCreditAssets carbonCreditAssets = new CarbonCreditAssets();
        // 复制参数到实体，排除id和projectId字段
        BeanUtil.copyProperties(param, carbonCreditAssets, "id", "projectId");
        // 查询碳项目元数据
        CarbonMetaregistryQueryVo cm = carbonMetaregistryMapper.getCarbonMetaregistryById(param.getCarbonProjectId());
        log.info("查询到的碳项目元数据: {}", JSONUtil.toJsonStr(cm));
        // 插入一个 CarbonMetaRegistryProject 记录
        CarbonMetaregistryProject project = new CarbonMetaregistryProject();
        project.setMetaregistryId(cm.getId());
        project.setTenantId(getCurrentTenantId());
        // 执行插入操作
        carbonMetaregistryProjectMapper.insert(project);
        log.info("新插入项目的ID: {}", project.getId());
        // 设置碳项目ID
        carbonCreditAssets.setCarbonProjectId(param.getCarbonProjectId());
        // 设置租户ID
        carbonCreditAssets.setTenantId(getCurrentTenantId());
        // 设置资产状态为待处理
        carbonCreditAssets.setAssetsStatus(AssetsStatus.WAIT.getStatus());
        // 设置交易状态为报价
        carbonCreditAssets.setTransactionStatus(AssetsTradeStatus.OFFER.getStatus());
        // 可用数量等于总数量
        carbonCreditAssets.setAvailableAmount(carbonCreditAssets.getTotal());
        // 估值等于总数量乘以50
        carbonCreditAssets.setValuation(carbonCreditAssets.getTotal().multiply(BigDecimal.valueOf(50)));
        // 认证机构等于碳项目元数据的认证标准
        carbonCreditAssets.setCertifiedAgency(cm.getCertifiedStandard());
        // 保存碳信用资产信息
        this.save(carbonCreditAssets);

        // 获取当前用户的安全数据
        SecurityData data = getLoginInfoVo().getSecurityData();
        // 构建资产上传审批信息并发送飞书审批
        AssetUploadApproval approval = AssetUploadApproval.builder()
                .id(carbonCreditAssets.getId())
                .userName(handleNull(data.getAccountName()))
                .agenciesName(handleNull(data.getTenantName()))
                .contactNumber(handleNull(data.getPhone()))
                .assetType(handleNull("碳信用"))
                .primaryMarketHoldingInstitutions(handleNull(null))
                .shareholding(handleNull(carbonCreditAssets.getTotal().toString()))
                .proofOfPosition(handleNull(carbonCreditAssets.getIssuingCertificates()))
                .issuingAgency(handleNull(carbonCreditAssets.getIssuingAgency()))
                .build();
        Message<AssetUploadApproval> msg = MessageBuilder.withPayload(approval).build();
        mqTemplate.syncSend(RocketMqName.AssetUploadApproval_MSG, msg, 3000, RocketDelayLevelConstant.SECOND5);

        // 异步调用区块链服务添加碳信用资产
        try {
            chainMakerServiceApi.addCreditAssets(BeanUtil.copyProperties(carbonCreditAssets, CarbonCreditAssetsParam.class));
        } catch (Exception e) {
            log.error("区块链消息异常!!");
        }
    }


    private String handleNull(String str){
        return str == null ? "-" : str;
    }

    @Override
    public CarbonAssetsTotalVo getCarbonAssetsTotal() {
        return carbonCreditAssetsMapper.getCarbonAssetsTotal();
    }

    @Override
    public boolean removeById(Serializable id) {
        Long projectId =  this.getBaseMapper().getCarbonCreditAssetsById(id).getCarbonProjectId();
        boolean res =  SqlHelper.retBool(this.getBaseMapper().deleteById(id));
        if(res){
            Optional.ofNullable(projectId).ifPresent(e->{
                carbonMetaregistryProjectMapper.deleteById(projectId);
            });
        }
        return res;
    }
}
